package cn.edu.usst.cs.goldfish.booking.meetingroom.web.controller;

import cn.edu.usst.cs.goldfish.booking.meetingroom.config.MeetingRoomsConfig;
import cn.edu.usst.cs.goldfish.booking.meetingroom.handler.GoldfishBookingAuthException;
import cn.edu.usst.cs.goldfish.booking.meetingroom.mapstruct.BookingMapper;
import cn.edu.usst.cs.goldfish.booking.meetingroom.model.Meeting;
import cn.edu.usst.cs.goldfish.booking.meetingroom.model.MeetingRoom;
import cn.edu.usst.cs.goldfish.booking.meetingroom.model.MeetingSlot;
import cn.edu.usst.cs.goldfish.booking.meetingroom.model.SysUser;
import cn.edu.usst.cs.goldfish.booking.meetingroom.mybatis.MeetingMapper;
import cn.edu.usst.cs.goldfish.booking.meetingroom.mybatis.MeetingRoomMapper;
import cn.edu.usst.cs.goldfish.booking.meetingroom.mybatis.MeetingSlotMapper;
import cn.edu.usst.cs.goldfish.booking.meetingroom.mybatis.UserMapper;
import cn.edu.usst.cs.goldfish.booking.meetingroom.service.BookingService;
import cn.edu.usst.cs.goldfish.booking.meetingroom.web.SessionKeys;
import cn.edu.usst.cs.goldfish.booking.meetingroom.web.dto.booking.BookingRecordDTO;
import cn.edu.usst.cs.goldfish.booking.meetingroom.web.dto.booking.Slot;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/api/bookings")
@RequiredArgsConstructor
public class BookingController {

    private final BookingService bookingService;
    private final MeetingRoomMapper meetingRoomMapper;
    private final MeetingRoomsConfig meetingRoomsConfig;
    private final MeetingSlotMapper meetingSlotMapper;
    private final BookingMapper bookingMapper;
    private final UserMapper userMapper;
    private final MeetingMapper meetingMapper;

    @GetMapping("/room/{roomId}/occupied-slots")
    public List<Slot> getOccupiedSlotsForRoomPerDay(
            @PathVariable Long roomId,
            @RequestParam
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
            LocalDate date
    ) {
        List<Slot> occupiedSlots = bookingService.getOccupiedSlotsOfARoom(roomId, date);
        log.warn("房号 {} 在 {} 的占用时段: {}", roomId, date, occupiedSlots);
        return occupiedSlots;
    }

    @GetMapping("/room/{roomId}/free-slots")
    public List<Slot> getFreeSlotsForRoomPerDay(
            @PathVariable Long roomId,
            @RequestParam
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
            LocalDate date
    ) {
        List<Slot> freeSlots = bookingService.getFreeSlotsOfARoomPerDay(roomId, date);
        log.warn("房号 {} 在 {} 的空闲时段: {}", roomId, date, freeSlots);
        return freeSlots;
    }


    @GetMapping("/rooms")
    public List<MeetingRoom> getAllRooms() {
        log.info("API调用: 获取所有会议室列表");
        List<MeetingRoom> result = meetingRoomMapper.selectAllRooms();
        log.info("API返回: {} 个会议室", result.size());
        return result;
    }


    @GetMapping("/config")
    public Map<String, Object> getBookingConfig() {
        Map<String, Object> config = new HashMap<>();
        config.put("startHour", meetingRoomsConfig.getStartHour());
        config.put("endHour", meetingRoomsConfig.getEndHour());
        config.put("breakMinutes", meetingRoomsConfig.getBreakMinutes());
        config.put("advanceDays", meetingRoomsConfig.getAdvanceDays());


        List<Meeting> meetings = meetingMapper.selectList(new QueryWrapper<>());
        List<Meeting> meetingsToday = meetings.stream()
                .filter(meeting -> {
                    List<MeetingSlot> meetingSlots = meetingSlotMapper.selectList(
                            new QueryWrapper<MeetingSlot>()
                                    .eq("meeting_id", meeting.getId())
                                    .eq("date", LocalDate.now())
                    );
                    return !meetingSlots.isEmpty();
                })
                .toList();

        config.put("totalMeetings", meetings.size());
        config.put("meetingsToday", meetingsToday.size());
        return config;
    }


    @PostMapping("/room/{roomId}/book")
    public void bookRoom(
            @PathVariable Long roomId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime end,
            @RequestParam String topic,
            @SessionAttribute(SessionKeys.EMAIL) String email) {

        if (email == null) {
            throw new GoldfishBookingAuthException("未登录或Session已过期");
        }

        // 根据email查询用户ID
        SysUser user = userMapper.selectOne(new QueryWrapper<SysUser>().eq("email", email));
        if (user == null) {
            throw new GoldfishBookingAuthException("用户不存在");
        }
        bookingService.bookARoom(roomId, user.getId(), start, end, topic);
    }

    @DeleteMapping("/{bookingId}/cancel")
    public void cancelBooking(@PathVariable Long bookingId) {
        bookingService.cancelBooking(bookingId);
    }

    @GetMapping("/my-bookings")
    public List<BookingRecordDTO> getMyBookings(@SessionAttribute(SessionKeys.EMAIL) String email) {
        if (email == null) {
            throw new GoldfishBookingAuthException("未登录或Session已过期");
        }
        return bookingService.getBookingsByUserEmail(email);
    }

    @GetMapping("/joinable-meetings")
    public List<Map<String, Object>> getJoinableMeetings() {
        return bookingService.getJoinableMeetings();
    }

    @GetMapping("/joined")
    public List<Map<String, Object>> getJoinedMeetings(
            @SessionAttribute(SessionKeys.EMAIL) String email
    ) {
        List<Meeting> meetings = bookingService.getJoinedMeetings(email);
        List<Map<String, Object>> result = new ArrayList<>();
        meetings.forEach((meeting) -> {
            Map<String, Object> meetingMap = new HashMap<>();
            meetingMap.put("id", meeting.getId());
            meetingMap.put("topic", meeting.getTopic());
            List<MeetingSlot> slots = meetingSlotMapper.selectList(
                    new QueryWrapper<MeetingSlot>()
                            .eq("meeting_id", meeting.getId())
            );
            if (!slots.isEmpty()) {
                MeetingSlot meetingSlot = slots.stream()
                        .min(Comparator.comparing(MeetingSlot::getTime))
                        .get();
//                Slot slot = bookingMapper.fromMeetingSlot(meetingSlot);
                meetingMap.put("time", meetingSlot.getTime());
                result.add(meetingMap);
            }
            MeetingRoom room = meetingRoomMapper.selectOne(
                    new QueryWrapper<MeetingRoom>().eq("id", meeting.getRoomId())
            );
            if (room != null) {
                meetingMap.put("roomName", room.getRoomName());
            }

        });
        return result;
    }
}
